package org.softmed.rest.server.defaults.handlers;

import java.io.File;
import java.util.List;
import java.util.Set;
import java.util.Map.Entry;

import groovy.lang.Binding;
import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyCodeSource;
import groovy.lang.GroovyShell;
import groovy.lang.Script;
import groovy.util.GroovyScriptEngine;
import groovy.util.ResourceException;
import groovy.util.ScriptException;

import org.softmed.filehandling.FileUtil;
import org.softmed.groovy.utils.GroovyCache;
import org.softmed.rest.config.Handler;
import org.softmed.rest.config.Parameter;
import org.softmed.rest.server.core.handler.HandlerProcessParameters;
import org.softmed.rest.server.core.handler.SpecificHandlerSolver;

import com.google.inject.Inject;

public class GroovySolver implements SpecificHandlerSolver {
	FileUtil util = new FileUtil();

	String headerCode = "import org.restlet.data.MediaType;\nimport org.restlet.data.Status;\n";

	// @Inject
	// GroovyClassLoader groovyClassLoader;
	//
	// @Inject
	// GroovyScriptEngine gse;

	@Inject
	GroovyCache groovyCache;

	boolean stop = false;

	@Override
	public boolean canSolve(Handler handler) {

		String path = handler.getPath();

		path = path.replace('.', '/');
		path += ".groovy";

		// needs fixing !!!
		File file = util.getFile(path);
		if (file == null || !file.exists())
			return false;

		// if (!groovyCache.exists(path))
		// return false;

		return true;
	}

	@Override
	public void solve(Handler handler, HandlerProcessParameters parameters)
			throws Throwable {
		// parameters.getRequest().getEntity().getText()
		String path = handler.getPath();
		path = path.replace('.', '/');
		// path = util.fixPath(path);
		path += ".groovy";

		try {

			Binding binding = new Binding();
			// TODO use java reflection to dynamize this
			binding.setVariable("application", parameters.getApplication());
			binding.setVariable("module", parameters.getModule());
			binding.setVariable("resource", parameters.getResource());
			binding.setVariable("httpMethod", parameters.getHttpMethod());
			binding.setVariable("mimeTypeHandler", parameters
					.getMimeTypeHandler());
			binding.setVariable("request", parameters.getRequest());
			binding.setVariable("response", parameters.getResponse());

			binding.setVariable("uriParameters", parameters.getUriParameters());
			binding.setVariable("queryParameters", parameters
					.getQueryParameters());

			binding.setVariable("parameters", handler.getParametersAsMap());

			// Script script = gse.createScript("", binding);
			// script.

			// set handler parameters to groovy bindings
			List<Parameter> params = handler.getParameters();
			for (Parameter parameter : params) {
				if (parameter.isActive())
					binding.setVariable(parameter.getName(), parameter
							.getValue());
				else
					binding.setVariable(parameter.getName(), null);
			}

			Set<Entry<String, Object>> entries = parameters
					.getSequenceParameters().entrySet();
			for (Entry<String, Object> entry : entries) {
				binding.setVariable(entry.getKey(), entry.getValue());
			}
			binding.setVariable("sequenceParameters", parameters
					.getSequenceParameters());

			// GroovyCodeSource gcs = new GroovyCodeSource();

			// String script = util.readFromFile(path);
			// script =
			// "import org.restlet.data.MediaType;\nimport org.restlet.data.Status;"
			// + script;
			// GroovyShell shell = new GroovyShell(groovyClassLoader, binding);
			// shell.evaluate(script);
			// gse.run(path, binding);

//			System.out.println("GROOVY CLASS LOADER FROM GROOVY SOLVER: " + groovyCache.getGroovyClassLoader());

			
			Script script = null;
			script = groovyCache.getCustomScript(path, headerCode);
			
			
			script.setBinding(binding);
			script.run();

			binding.getVariables().remove("sequenceParameters");
			binding.getVariables().remove("parameters");
			binding.getVariables().remove("queryParameters");
			binding.getVariables().remove("uriParameters");
			binding.getVariables().remove("response");
			binding.getVariables().remove("request");

			binding.getVariables().remove("httpMethod");
			binding.getVariables().remove("mimeTypeHandler");

			binding.getVariables().remove("resource");
			binding.getVariables().remove("module");
			binding.getVariables().remove("application");

			for (Parameter parameter : params) {
				binding.getVariables().remove(parameter.getName());
			}

			parameters.getSequenceParameters().clear();
			Set<Entry<String, Object>> remainingVariables = binding
					.getVariables().entrySet();
			for (Entry<String, Object> entry : remainingVariables) {
				parameters.getSequenceParameters().put(entry.getKey(),
						entry.getValue());
			}

			try {
				stop = (Boolean) binding.getVariable("stop");
				System.out.println("Stop processing = " + stop);
			} catch (Throwable t) {
				// t.printStackTrace();
			}

		} catch (ResourceException e) {
			e.printStackTrace();
		} catch (ScriptException e) {
			e.printStackTrace();
		}

	}

	@Override
	public boolean isContinueProcessing() {
		return !stop;
	}

	@Override
	public SpecificHandlerSolver getClone() {
		GroovySolver clone = new GroovySolver();
		clone.groovyCache = groovyCache;
		return clone;
	}

}
